/**
 * 网络状态检测工具
 */

// 网络状态管理
class NetworkManager {
  constructor() {
    this.isOnline = navigator.onLine
    this.listeners = new Set()
    this.retryQueue = new Map()
    this.retryCount = 0
    this.maxRetries = 3
    this.retryDelay = 1000
    
    this.init()
  }
  
  init() {
    // 监听网络状态变化
    window.addEventListener('online', this.handleOnline.bind(this))
    window.addEventListener('offline', this.handleOffline.bind(this))
    
    // 定期检测网络连接
    this.startHeartbeat()
  }
  
  // 添加网络状态监听器
  addListener(callback) {
    this.listeners.add(callback)
    return () => this.listeners.delete(callback)
  }
  
  // 通知所有监听器
  notifyListeners(status) {
    this.listeners.forEach(callback => {
      try {
        callback(status)
      } catch (error) {
        console.error('Network listener error:', error)
      }
    })
  }
  
  // 网络连接恢复
  handleOnline() {
    this.isOnline = true
    this.retryCount = 0
    this.notifyListeners({ online: true, type: 'online' })
    this.processRetryQueue()
  }
  
  // 网络连接断开
  handleOffline() {
    this.isOnline = false
    this.notifyListeners({ online: false, type: 'offline' })
  }
  
  // 检测网络连接质量
  async checkConnection() {
    if (!navigator.onLine) {
      return { online: false, quality: 'offline' }
    }
    
    try {
      const start = Date.now()
      const response = await fetch('/api/ping', {
        method: 'HEAD',
        cache: 'no-cache',
        timeout: 5000
      })
      const duration = Date.now() - start
      
      if (response.ok) {
        let quality = 'good'
        if (duration > 2000) quality = 'poor'
        else if (duration > 1000) quality = 'fair'
        
        return { online: true, quality, latency: duration }
      } else {
        return { online: false, quality: 'error', status: response.status }
      }
    } catch (error) {
      return { online: false, quality: 'error', error: error.message }
    }
  }
  
  // 开始心跳检测
  startHeartbeat() {
    setInterval(async () => {
      const status = await this.checkConnection()
      if (status.online !== this.isOnline) {
        this.isOnline = status.online
        this.notifyListeners(status)
      }
    }, 30000) // 每30秒检测一次
  }
  
  // 添加重试请求到队列
  addToRetryQueue(requestId, requestFn, options = {}) {
    this.retryQueue.set(requestId, {
      fn: requestFn,
      retries: 0,
      maxRetries: options.maxRetries || this.maxRetries,
      delay: options.delay || this.retryDelay,
      timestamp: Date.now()
    })
  }
  
  // 处理重试队列
  async processRetryQueue() {
    if (!this.isOnline || this.retryQueue.size === 0) return
    
    const promises = []
    for (const [requestId, request] of this.retryQueue.entries()) {
      promises.push(this.retryRequest(requestId, request))
    }
    
    await Promise.allSettled(promises)
  }
  
  // 重试单个请求
  async retryRequest(requestId, request) {
    try {
      const result = await request.fn()
      this.retryQueue.delete(requestId)
      return result
    } catch (error) {
      request.retries++
      if (request.retries >= request.maxRetries) {
        this.retryQueue.delete(requestId)
        throw error
      } else {
        // 指数退避重试
        const delay = request.delay * Math.pow(2, request.retries)
        setTimeout(() => {
          if (this.isOnline) {
            this.retryRequest(requestId, request)
          }
        }, delay)
      }
    }
  }
  
  // 获取网络信息
  getNetworkInfo() {
    const connection = navigator.connection || navigator.mozConnection || navigator.webkitConnection
    
    return {
      online: this.isOnline,
      type: connection?.effectiveType || 'unknown',
      downlink: connection?.downlink || 0,
      rtt: connection?.rtt || 0,
      saveData: connection?.saveData || false
    }
  }
  
  // 清理资源
  destroy() {
    window.removeEventListener('online', this.handleOnline)
    window.removeEventListener('offline', this.handleOffline)
    this.listeners.clear()
    this.retryQueue.clear()
  }
}

// 创建全局网络管理器实例
export const networkManager = new NetworkManager()

// 网络状态检测装饰器
export function withNetworkRetry(options = {}) {
  return function(target, propertyKey, descriptor) {
    const originalMethod = descriptor.value
    
    descriptor.value = async function(...args) {
      const requestId = `${propertyKey}_${Date.now()}_${Math.random()}`
      
      try {
        return await originalMethod.apply(this, args)
      } catch (error) {
        if (isNetworkError(error) && networkManager.isOnline) {
          // 添加到重试队列
          networkManager.addToRetryQueue(
            requestId,
            () => originalMethod.apply(this, args),
            options
          )
        }
        throw error
      }
    }
    
    return descriptor
  }
}

// 判断是否为网络错误
export function isNetworkError(error) {
  return (
    error.code === 'NETWORK_ERROR' ||
    error.message.includes('Network Error') ||
    error.message.includes('fetch') ||
    !navigator.onLine
  )
}

// 网络状态 Hook (需要在Vue组件中使用)
export function useNetworkStatus() {
  // 这个函数需要在Vue组件中使用，需要导入Vue的相关函数
  // import { ref, readonly, onMounted, onUnmounted } from 'vue'

  return {
    getNetworkInfo: () => networkManager.getNetworkInfo(),
    checkConnection: () => networkManager.checkConnection(),
    addToRetryQueue: (id, fn, options) => networkManager.addToRetryQueue(id, fn, options),
    addListener: (callback) => networkManager.addListener(callback)
  }
}

// 请求重试工具函数
export async function retryRequest(requestFn, options = {}) {
  const {
    maxRetries = 3,
    delay = 1000,
    backoff = true,
    condition = () => true
  } = options
  
  let lastError
  
  for (let i = 0; i <= maxRetries; i++) {
    try {
      const result = await requestFn()
      return result
    } catch (error) {
      lastError = error
      
      // 检查是否应该重试
      if (i === maxRetries || !condition(error)) {
        break
      }
      
      // 计算延迟时间
      const currentDelay = backoff ? delay * Math.pow(2, i) : delay
      await new Promise(resolve => setTimeout(resolve, currentDelay))
    }
  }
  
  throw lastError
}

// 网络质量检测
export async function measureNetworkQuality() {
  const tests = []
  
  // 测试延迟
  for (let i = 0; i < 3; i++) {
    const start = Date.now()
    try {
      await fetch('/api/ping', { method: 'HEAD', cache: 'no-cache' })
      tests.push(Date.now() - start)
    } catch {
      tests.push(Infinity)
    }
  }
  
  const avgLatency = tests.reduce((a, b) => a + b, 0) / tests.length
  
  let quality = 'excellent'
  if (avgLatency > 2000) quality = 'poor'
  else if (avgLatency > 1000) quality = 'fair'
  else if (avgLatency > 500) quality = 'good'
  
  return {
    latency: avgLatency,
    quality,
    tests
  }
}

export default networkManager
